package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.bean.Setmeal;
import com.itheima.bean.SetmealDish;
import com.itheima.common.PageParam;
import com.itheima.dao.SetmealDao;
import com.itheima.dto.SetmealDto;
import com.itheima.exception.CustomException;
import com.itheima.service.CategoryService;
import com.itheima.service.SetmealDishService;
import com.itheima.service.SetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Transactional
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealDao , Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private CategoryService categoryService;

    /**
     * 新增套餐
     * 1. 套餐的数据包含两部分： 套餐本身的数据， 套餐包含的菜品数据
     * 2. 需要往两张表里面存储： 套餐表（steaml）, 套餐菜品表（setmeal_dish）
     * 3. 先往套餐表存数据，这样就能产生套餐的id值。
     * 4. 接着再包套餐包含的菜品数据，挨个保存到套餐菜品表里面去。同时
     * 保存之前，要设置菜品数据属于哪个套餐！设置套餐的id。
     * 5. 这个操作和前面的新增菜品是一样的道理！
     *
     * @param setmealDto
     * @return
     */
    @Override
    public int add(SetmealDto setmealDto) {

        //1. 先往套餐表添加数据:: 只要是使用MP执行的添加，添加成功之后，会自动的把记录的主键id，填充到对象的id属性上。
        int row = getBaseMapper().insert(setmealDto);

        //2. 再往套餐菜品表添加数据
        List<SetmealDish> setmealDishList = setmealDto.getSetmealDishes().stream().map((setmealDish) -> {
            //给每一个套餐菜品对象，设置关联的套餐id
            setmealDish.setSetmealId(setmealDto.getId());
            return setmealDish;
        }).collect(Collectors.toList());

        //使用批量的方式来添加
        boolean result = setmealDishService.saveBatch(setmealDishList);


        return row > 0 && result ? 1 : 0;
    }

    /**
     * 套餐分页
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<SetmealDto> page(PageParam pageParam) {

        //1. 先查询套餐表
        //1.1 设置分页
        IPage<Setmeal> setmealIPage = new Page<>(pageParam.getPage() , pageParam.getPageSize());

        //1.2 设置条件
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();
        lqw.like(pageParam.getName() != null , Setmeal::getName , pageParam.getName());

        //1.3 执行分页查询:: 不能直接返回这个结果
        IPage<Setmeal> setmealPage = getBaseMapper().selectPage(setmealIPage, lqw);


        //2. 构建IPage<SetmealDto>
        IPage<SetmealDto> dtoPage = new Page<>();

        //2.1 设置总数
        dtoPage.setTotal(setmealIPage.getTotal());

        //2.2 设置集合数

        //2.2.1 构建一个集合装SetmealDto对象
        List<SetmealDto> dtoList = setmealIPage.getRecords().stream().map(setmeal -> {

            //2.2.2 一个setmeal就要映射成一个setmealDto对象
            SetmealDto dto = new SetmealDto();

            //2.2.3 拷贝数据过来
            BeanUtils.copyProperties(setmeal, dto);

            //2.2.4 还缺少分类数据
            String categoryName = categoryService.getById(setmeal.getCategoryId()).getName();
            dto.setCategoryName(categoryName);

            //TODO:: 2.2.5 还缺少套餐的菜品数据...

            return dto;
        }).collect(Collectors.toList());

        dtoPage.setRecords(dtoList);
        return dtoPage;
    }

    /**
     * 删除套餐
     *  1. 不能直接认为就是去删除套餐表的数据这么简单!
     *  2. 步骤应该是这样：
     *      2.1 先检查要删除的套餐是不是处于售卖的状态， 如果是，那么禁止删除。
     *      2.2 只有套餐处于停售的状态，才能删除套餐
     *      2.3 删除套餐，要把两张表的数据都删除了。
     *          2.3.1 套餐表的数据
     *          2.3.2 套餐菜品表的数据。
     * @param ids
     * @return
     */
    @Override
    public int delete(List<Long> ids) {

        //1. 检查套餐的状态是否处于售卖情况 : 1,3,5
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();

        //1.1 设置条件 select * from setmeal where id in (1,3,5)
        lqw.in(Setmeal::getId , ids);

        //1.2  select * from setmeal where id in (1,3,5) and status = 1
        lqw.eq(Setmeal::getStatus , 1) ;

        //1.3 查询数量 select count(*) from setmeal where id in (1,3,5) and status = 1
        long count = this.count(lqw);

        //有套餐处于售卖状态，禁止删除！
        if(count > 0){
            throw new CustomException("有套餐处于售卖状态，禁止删除！");
        }

        //2. 没有套餐处于售卖状态，那么就可以删除了。

        //2.1 删除套餐表:: 批量删除套餐
        boolean result = this.removeBatchByIds(ids);

        //2.2 删除套餐菜品表
        LambdaQueryWrapper<SetmealDish> sdQW  = new LambdaQueryWrapper<>();
        //语句： delete from setmealdish where stemealid in (1,3,5);
        sdQW.in(SetmealDish::getSetmealId , ids);

        boolean result2 = setmealDishService.remove(sdQW);

        return result && result2 ? 1 : 0;
    }
}
